import ContactLink from "./contact-link";
import CachedDetectorData from "../../collision-detector/cached-detector-data";
import DetectorResult from "../../collision-detector/detector-result";
import Manifold from "./manifold";
import ManifoldUpdater from "./manifold-updater";
import ContactConstraint from "./contact-constraint";
import CONSTANT from "../../constant";

export default class Contact {
    constructor() {
        this._next = null;
        this._prev = null;
        this._link1 = new ContactLink();
        this._link2 = new ContactLink();
        this._s1 = null;
        this._s2 = null;
        this._b1 = null;
        this._b2 = null;
        this._detector = null;
        this._cachedDetectorData = new CachedDetectorData();
        this._detectorResult = new DetectorResult();
        this._latest = false;
        this._shouldBeSkipped = false;
        this._manifold = new Manifold();
        this._updater = new ManifoldUpdater(this._manifold);
        this._contactConstraint = new ContactConstraint(this._manifold);
        this._touching = false;
    }
    _updateManifold() {
        if(this._detector == null) {
            return;
        }
        let ptouching = this._touching;
        let result = this._detectorResult;
        this._detector.detect(result,this._s1._geom,this._s2._geom,this._s1._transform,this._s2._transform,this._cachedDetectorData);
        this._touching = result.numPoints > 0;
        if(this._touching) {
            this._manifold._buildBasis(result.normal);
            if(result.getMaxDepth() > CONSTANT.SETTING_CONTACT_USE_ALTERNATIVE_POSITION_CORRECTION_ALGORITHM_DEPTH_THRESHOLD) {
                this._contactConstraint._positionCorrectionAlgorithm = CONSTANT.SETTING_ALTERNATIVE_CONTACT_POSITION_CORRECTION_ALGORITHM;
            } else {
                this._contactConstraint._positionCorrectionAlgorithm = CONSTANT.SETTING_DEFAULT_CONTACT_POSITION_CORRECTION_ALGORITHM;
            }
            if(result.incremental) {
                this._updater.incrementalUpdate(result,this._b1._transform,this._b2._transform);
            } else {
                this._updater.totalUpdate(result,this._b1._transform,this._b2._transform);
            }
        } else {
            this._manifold._clear();
        }
        if(this._touching && !ptouching) {
            let cc1 = this._s1._contactCallback;
            let cc2 = this._s2._contactCallback;
            if(cc1 === cc2) {
                cc2 = null;
            }
            if(cc1 != null) {
                cc1.beginContact(this);
            }
            if(cc2 != null) {
                cc2.beginContact(this);
            }
        }
        if(!this._touching && ptouching) {
            let cc1 = this._s1._contactCallback;
            let cc2 = this._s2._contactCallback;
            if(cc1 === cc2) {
                cc2 = null;
            }
            if(cc1 != null) {
                cc1.endContact(this);
            }
            if(cc2 != null) {
                cc2.endContact(this);
            }
        }
        if(this._touching) {
            let cc1 = this._s1._contactCallback;
            let cc2 = this._s2._contactCallback;
            if(cc1 === cc2) {
                cc2 = null;
            }
            if(cc1 != null) {
                cc1.preSolve(this);
            }
            if(cc2 != null) {
                cc2.preSolve(this);
            }
        }
    }
    _postSolve() {
        let cc1 = this._s1._contactCallback;
        let cc2 = this._s2._contactCallback;
        if(cc1 === cc2) {
            cc2 = null;
        }
        if(cc1 != null) {
            cc1.postSolve(this);
        }
        if(cc2 != null) {
            cc2.postSolve(this);
        }
    }
    getShape1() {
        return this._s1;
    }
    getShape2() {
        return this._s2;
    }
    isTouching() {
        return this._touching;
    }
    getManifold() {
        return this._manifold;
    }
    getContactConstraint() {
        return this._contactConstraint;
    }
    getPrev() {
        return this._prev;
    }
    getNext() {
        return this._next;
    }
}